import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:fast_image_compress/fast_image_compress.dart';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fast Image Compress Example',
      theme: ThemeData(
        primarySwatch: Colors.red,
      ),
      home: const CompressionExamplePage(),
    );
  }
}

class CompressionExamplePage extends StatefulWidget {
  const CompressionExamplePage({super.key});

  @override
  CompressionExamplePageState createState() => CompressionExamplePageState();
}

class CompressionExamplePageState extends State<CompressionExamplePage> {
  final FastImageCompress fastImageCompress = FastImageCompress();
  final ImagePicker _imagePicker = ImagePicker();
  List<Uint8List>? _originalImageList;
  List<Uint8List>? _compressedImageList;
  bool _isCompressing = false;
  double _progress = 0.0;
  int _completedCount = 0;
  bool _isCancelled = false;

  @override
  void initState() {
    super.initState();
  }

  // 重置所有状态
  void _resetAllState() {
    _isCancelled = false;
    if (mounted) {
      setState(() {
        _isCompressing = false;
        _progress = 0.0;
        _completedCount = 0;
        _compressedImageList = null;
        _originalImageList = null; // 清空原始图片列表
      });
    }
  }

  Future<void> _pickImage() async {
    try {
      _resetAllState();

      final pickedFiles = await _imagePicker.pickMultiImage();
      if (pickedFiles.isNotEmpty) {
        final res = await Future.wait(
          pickedFiles.map((file) async => await file?.readAsBytes()),
        );
        if (mounted) {
          setState(() {
            _originalImageList = res.cast<Uint8List>();
          });
        }
      } else {
        if (mounted) {
          setState(() {
            _originalImageList = [];
          });
        }
      }
    } catch (e) {
      print('选择图片出错: $e');
      if (mounted) {
        setState(() {
          _originalImageList = [];
        });
      }
    }
  }

  // 压缩按钮点击处理 - 优化状态重置和任务启动
  void _onCompressButtonPressed() {
    print('Compress button clicked - before: isCompressing=$_isCompressing, isCancelled=$_isCancelled');
    
    // 安全检查
    if (_originalImageList == null || _originalImageList!.isEmpty) {
      print('没有选择图片');
      return;
    }
    
    // 关键修改：完全重置所有状态，确保没有残留的取消标志影响
    _isCancelled = false;
    
    // 先更新内部状态，再更新UI
    _isCompressing = true;
    
    // 更新UI状态
    if (mounted) {
      setState(() {
        _isCompressing = true;
        _progress = 0.0;
        _completedCount = 0;
        _compressedImageList = null;
      });
    }
    
    print('Compress button clicked - after reset: isCompressing=$_isCompressing, isCancelled=$_isCancelled');
    
    // 使用Future.microtask确保状态完全更新后再启动压缩任务
    // 这可以避免在状态尚未完全更新时启动任务导致的问题
    Future.microtask(() {
      print('Starting compression task from microtask - isCompressing=$_isCompressing, isCancelled=$_isCancelled');
      _startCompressionTask(1);
    });
  }

  // 取消压缩方法 - 简洁可靠的取消处理
  void _cancelCompression() {
    print('Cancel button clicked - before: isCompressing=$_isCompressing, isCancelled=$_isCancelled');
    
    // 立即设置取消标志
    _isCancelled = true;
    
    try {
      // 调用库的取消方法
      fastImageCompress.cancelCompression();
    } catch (e) {
      print('取消压缩出错: $e');
    }
    
    // 立即重置UI状态
    if (mounted) {
      setState(() {
        _isCompressing = false;
        _progress = 0.0;
        _completedCount = 0;
        _compressedImageList = null;
		_originalImageList = null; // 清除选择的图片，
      });
    }
    
    print('Cancel button clicked - after: isCompressing=$_isCompressing, isCancelled=$_isCancelled');
  }

  // 实际执行压缩的异步方法 - 增强错误处理和重试机制
  Future<void> _startCompressionTask(int taskId) async {
    print('Starting compression task $taskId - isCompressing=$_isCompressing, isCancelled=$_isCancelled');

    // 如果任务已经被取消，直接返回
    if (_isCancelled) {
      print('Task $taskId skipped - already cancelled');
      _resetCompressionState();
      _isCancelled = false;
      return;
    }

    final totalImages = _originalImageList!.length;
    final List<Uint8List> compressedResults = [];

    try {
      // 逐个压缩图片
      for (int i = 0; i < totalImages; i++) {
        // 检查是否已取消
        if (_isCancelled) {
          print('Task $taskId cancelled during iteration $i');
          _resetCompressionState();
          return;
        }

        // 更新进度
        if (mounted && !_isCancelled) {
          setState(() {
            _progress = (i + 1) / totalImages;
            _completedCount = i + 1;
          });
        }

        // 压缩单个图片 - 添加重试机制
        Uint8List? compressedImage;
        int retryCount = 0;
        const maxRetries = 2;
        
        while (compressedImage == null && retryCount <= maxRetries && !_isCancelled) {
          if (retryCount > 0) {
            print('Task $taskId retrying compression for image $i, attempt ${retryCount+1}');
            // 短暂延迟后重试
            await Future.delayed(const Duration(milliseconds: 100));
          }
          
          try {
            compressedImage = await fastImageCompress.compressImage(
              imageData: _originalImageList![i],
              quality: 90,
              targetWidth: 300,
              imageQuality: ImageQuality.high,
            );
          } catch (e) {
            print('Compression exception for image $i, attempt ${retryCount+1}: $e');
            compressedImage = null;
          }
          
          retryCount++;
          
          // 检查是否已取消
          if (_isCancelled) {
            print('Task $taskId cancelled during retry');
            _resetCompressionState();
            return;
          }
        }

        if (compressedImage != null) {
          compressedResults.add(compressedImage);
        } else {
          print('Task $taskId failed after $maxRetries retries - compression returned null');
          _resetCompressionState();
          return;
        }
      }

      // 最终检查：确保任务未被取消
      if (_isCancelled) {
        print('Task $taskId cancelled before final update');
        _resetCompressionState();
        return;
      }

      // 成功完成压缩
      if (mounted && !_isCancelled) {
        setState(() {
          _compressedImageList = compressedResults;
          _isCompressing = false;
          _progress = 1.0;
        });
      }
    } catch (e) {
      print('Compression error in task $taskId: $e');
      _resetCompressionState();
    } finally {
      // 确保取消标志被重置
      _isCancelled = false;
      print('Task $taskId finished - reset _isCancelled to false');
    }
  }

  // 辅助方法：重置压缩相关状态
  void _resetCompressionState() {
    if (mounted) {
      setState(() {
        _isCompressing = false;
        _progress = 0.0;
        _completedCount = 0;
        _compressedImageList = null;
		_originalImageList = null; // 清除选择的图片
      });
    }
    print('Compression state reset - originalImageList cleared');
  }

  @override
  Widget build(BuildContext context) {
    final totalSelectedImages = _originalImageList?.length ?? 0;
    return Scaffold(
      appBar: AppBar(
        title: const Text('Image Compression Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            // 选择图片按钮
            ElevatedButton(
              onPressed: _pickImage,
              child: const Text('Pick Image'),
            ),

            // 显示选中的图片数量
            if (_originalImageList != null) ...[
              const SizedBox(height: 20),
              Text('Selected image count: $totalSelectedImages'),
            ],

            const SizedBox(height: 20),

            // 压缩/取消按钮 - 使用单个按钮，根据状态切换文本和行为
            ElevatedButton(
              onPressed: _isCompressing
                  ? _cancelCompression
                  : _onCompressButtonPressed,
              child: Text(
                  _isCompressing ? 'Cancel Compression' : 'Compress Image'),
            ),
            const SizedBox(height: 20),

            // 进度条
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 8.0),
              child: LinearProgressIndicator(value: _progress),
            ),

            const SizedBox(height: 10),

            // 进度文本
            if (totalSelectedImages > 0)
              Text(
                '$_completedCount/$totalSelectedImages Compressed',
                style: const TextStyle(fontSize: 16.0),
              ),

            // 显示压缩结果
            if (!_isCompressing &&
                _compressedImageList != null &&
                _compressedImageList!.isNotEmpty) ...[
              const SizedBox(height: 20),
              const Text('Compressed Images:'),
              const SizedBox(height: 20),
              Expanded(
                child: ListView.builder(
                  itemCount: _compressedImageList!.length,
                  itemBuilder: (BuildContext context, int index) {
                    // 确保索引有效
                    if (index >= _originalImageList!.length ||
                        index >= _compressedImageList!.length) {
                      return const SizedBox(height: 0);
                    }

                    // 计算大小
                    final originalSize =
                        (_originalImageList![index].lengthInBytes / 1024)
                            .toStringAsFixed(2);
                    final compressedSize =
                        (_compressedImageList![index].lengthInBytes / 1024)
                            .toStringAsFixed(2);

                    return Card(
                      margin: const EdgeInsets.all(16.0),
                      child: Padding(
                        padding: const EdgeInsets.all(16.0),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text(
                              'Image ${index + 1}',
                              style: const TextStyle(
                                fontSize: 18.0,
                                fontWeight: FontWeight.bold,
                              ),
                            ),
                            const SizedBox(height: 16.0),
                            const Text('Original Image:'),
                            const SizedBox(height: 8.0),
                            Image.memory(
                              _originalImageList![index],
                              height: 200,
                              fit: BoxFit.contain,
                            ),
                            const SizedBox(height: 16.0),
                            const Text('Compressed Image:'),
                            const SizedBox(height: 8.0),
                            Image.memory(
                              _compressedImageList![index],
                              height: 200,
                              fit: BoxFit.contain,
                            ),
                            const SizedBox(height: 16.0),
                            Text(
                              'Original Size: $originalSize Kb',
                              style:
                                  const TextStyle(fontWeight: FontWeight.bold),
                            ),
                            Text(
                              'Compressed Size: $compressedSize Kb',
                              style:
                                  const TextStyle(fontWeight: FontWeight.bold),
                            ),
                            Text(
                              'Compression Ratio: ${(double.parse(compressedSize) / double.parse(originalSize) * 100).toStringAsFixed(1)}%',
                              style: const TextStyle(color: Colors.green),
                            ),
                          ],
                        ),
                      ),
                    );
                  },
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _isCancelled = true;
    fastImageCompress.dispose();
    super.dispose();
  }
}
